﻿using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;
using System.Text.Encodings.Web;
using System.Text.Unicode;
using XUCore.Ddd.Domain;
using XUCore.Extensions;
using XUCore.NetCore.Authorization;
using XUCore.NetCore.Captcha;
using XUCore.NetCore.Captcha.Generator;
using XUCore.NetCore.DynamicWebApi;
using XUCore.NetCore.RestFul;
using XUCore.NetCore.Signature;
using XUCore.NetCore.Swagger;
using XUCore.Serializer;

namespace XUCore.NetCore.ApiTests;

/// <summary>
/// 注册服务
/// </summary>
public static class DependencyInjection
{
    /// <summary>
    /// 注册应用层
    /// </summary>
    /// <param name="services"></param>
    /// <param name="configuration"></param>
    /// <param name="environment"></param>
    /// <param name="serviceMode"></param>
    /// <returns></returns>
    public static IServiceCollection AddApplication(this IServiceCollection services, IConfiguration configuration, IHostEnvironment environment, string serviceMode = "api")
    {
        services.AddSingleton(HtmlEncoder.Create(UnicodeRanges.All));

        services.AddHttpContextAccessor();

        //services.AddHttpSignService();

        services.AddJwt<JwtHandler>(enableGlobalAuthorize: true);

        services
            .AddControllers(opts =>
            {
                opts.Filters.Add<ApiExceptionFilter>();
            })
            .AddRestFulFormatters(opts =>
            {
                opts.ResolverDefault = ResolverMode.CamelCase;
            });

        services.AddDynamicWebApi(opt =>
        {
            //opt.DefaultApiPrefix = "myapi";
            opt.GetRestFulRouteTemplate = (opt) =>
            {
                var route = "";

                if (opt.Version.NotEmpty())
                    route = $"{opt.ApiPreFix}/{opt.AreaName}/{opt.Version}/{opt.ControllerName}/{opt.ActionName}";
                else
                    route = $"{opt.ApiPreFix}/{opt.AreaName}/{opt.ControllerName}/{opt.ActionName}";

                return route;
            };
            //opt.IsRemoveVerbs = false;
            // opt.SplitActionCamelCase = true;
            // opt.SplitActionCamelCaseSeparator = "/";
        });

        // 自定义配置
        //services.AddDynamicWebApi((options) =>
        //{
        //    // 指定全局默认的 api 前缀
        //    options.DefaultApiPrefix = "apis";

        //    /**
        //     * 清空API结尾，不删除API结尾;
        //     * 若不清空 CreatUserAsync 将变为 CreateUser
        //     */
        //    options.RemoveActionPostfixes.Clear();

        //    /**
        //     * 自定义 ActionName 处理函数;
        //     */
        //    options.GetRestFulActionName = (actionName) => actionName;

        //    /**
        //     * 指定程序集 配置 url 前缀为 apis
        //     * 如: http://localhost:8080/apis/User/CreateUser
        //     */
        //    options.AddAssemblyOptions(this.GetType().Assembly, apiPreFix: "apis");

        //    /**
        //     * 指定程序集 配置所有的api请求方式都为 POST
        //     */
        //    options.AddAssemblyOptions(this.GetType().Assembly, httpVerb: "POST");

        //    /**
        //     * 指定程序集 配置 url 前缀为 apis, 且所有请求方式都为POST
        //     * 如: http://localhost:8080/apis/User/CreateUser
        //     */
        //    options.AddAssemblyOptions(this.GetType().Assembly, apiPreFix: "apis", httpVerb: "POST");
        //});

        //services.AddDynamicWebApi<ServiceLocalSelectController, ServiceActionRouteFactory>();



        // 内存存储， 基于appsettings.json配置
        services.AddCaptcha(configuration, options =>
        {
            // 自定义字体
            //options.ImageOption.FontSize = 28;
            //options.ImageOption.FontFamily = ResourceFontFamilysFinder.Find("KG HAPPY");
        });
        // 如果开启随机验码，请打开注释即可。
        services.AddScoped<ICaptcha, RandomCaptcha>();

        // Core项目使用的是IDistributedCache，
        // 如果使用redis缓存，需要安装包 Microsoft.Extensions.Caching.StackExchangeRedis
        // 参考：https://docs.microsoft.com/zh-cn/aspnet/core/performance/caching/distributed
        //services.AddStackExchangeRedisCache(options =>
        //{
        //    options.Configuration = builder.Configuration.GetConnectionString("RedisCache");
        //    options.InstanceName = "captcha:";
        //});

        // Core项目使用的是IDistributedCache，
        // 如果使用SQLServer缓存，则安装 Microsoft.Extensions.Caching.SqlServer
        //services.AddDistributedSqlServerCache(options =>
        //{
        //    options.ConnectionString = builder.Configuration.GetConnectionString(
        //        "DistCache_ConnectionString");
        //    options.SchemaName = "dbo";
        //    options.TableName = "TestCache";
        //});

        // -----------------------------------------------------------------------------
        // 全部配置参数，基于代码配置
        //services.AddCaptcha(configuration, option =>
        //{
        //    option.CaptchaType = CaptchaType.WORD; // 验证码类型
        //    option.CodeLength = 6; // 验证码长度, 要放在CaptchaType设置后.  当类型为算术表达式时，长度代表操作的个数
        //    option.ExpirySeconds = 30; // 验证码过期时间
        //    option.IgnoreCase = true; // 比较时是否忽略大小写
        //    option.StoreageKeyPrefix = ""; // 存储键前缀

        //    option.ImageOption.Animation = true; // 是否启用动画
        //    option.ImageOption.FrameDelay = 30; // 每帧延迟,Animation=true时有效, 默认30

        //    option.ImageOption.Width = 150; // 验证码宽度
        //    option.ImageOption.Height = 50; // 验证码高度
        //    option.ImageOption.BackgroundColor = SixLabors.ImageSharp.Color.White; // 验证码背景色

        //    option.ImageOption.BubbleCount = 2; // 气泡数量
        //    option.ImageOption.BubbleMinRadius = 5; // 气泡最小半径
        //    option.ImageOption.BubbleMaxRadius = 15; // 气泡最大半径
        //    option.ImageOption.BubbleThickness = 1; // 气泡边沿厚度

        //    option.ImageOption.InterferenceLineCount = 2; // 干扰线数量

        //    option.ImageOption.FontSize = 36; // 字体大小
        //    option.ImageOption.FontFamily = DefaultFontFamilys.Instance.Actionj; // 字体，中文使用kaiti，其他字符可根据喜好设置（可能部分转字符会出现绘制不出的情况）。
        //});

        // 注意： appsettings.json配置和代码配置同时设置时，代码配置会覆盖appsettings.json配置。


        services.AddMiniSwagger(swaggerGenAction: (opt) =>
        {
            opt.SwaggerDoc("test", new OpenApiInfo
            {
                Version = "v1.0.0",
                Title = $"test",
                Description = "test"
            });

            opt.AddJwtBearerDoc();
            //opt.AddHttpSignDoc(services);
            //opt.AddFiledDoc();
            //opt.AddHiddenApi();
            opt.AddDescriptions(typeof(Program), "XUCore.NetCore.ApiTests.xml");

            // TODO:一定要返回true！
            opt.DocInclusionPredicate((docName, description) => true);
        });

        return services;
    }
    /// <summary>
    /// 启用应用岑
    /// </summary>
    /// <param name="app"></param>
    /// <param name="env"></param>
    /// <returns></returns>
    public static IApplicationBuilder UseApplication(this IApplicationBuilder app, IWebHostEnvironment env)
    {

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        // app.UseDynamicWebApi((serviceProvider, options) =>
        // {
        //     options.AddAssemblyOptions(typeof(MyService).Assembly, "myapi");
        // });

        app.UseStaticFiles();
        app.UseRealIp();
        app.UseStaticHttpContext();

        //app.UseHttpSign<SignMiddlewareDemo>();

        app.UseRouting();

        app.UseAuthorization();

        app.UseAuthentication();

        app.UseMiniSwagger(swaggerUIAction: (opt) =>
        {
            opt.SwaggerEndpoint($"/swagger/test/swagger.json", "test API");
        });

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });

        return app;
    }
}
